package cn.piesat.scanning.business.common.algorithm.dataDistribute;

import com.alibaba.fastjson.JSON;
import cn.piesat.scanning.business.common.AlgorithmDefineAbstract;
import cn.piesat.scanning.dto.*;
import cn.piesat.scanning.service.*;
import cn.piesat.scanning.utils.FTPUtil;
import cn.piesat.scanning.utils.IpUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @author xhl
 */
@Component
public class FtpPublish extends AlgorithmDefineAbstract {

    private static final Logger logger = LoggerFactory.getLogger(FtpPublish.class);

    private static final String PRODUCT_DISTRIBUTE_TYPE = "p_distri";

    @Autowired
    private HtPathConfigurationService htPathConfigurationService;
    @Autowired
    private HtScheduleJobService htScheduleJobService;
    @Autowired
    private DbDmsAlgorithmResultStoreService dbDmsAlgorithmResultStoreService;
    @Autowired
    private DbDmsProductDistributeRecodeService dbDmsProductDistributeRecodeService;
    @Autowired
    private DbDmsSchedulerTaskFileRecordService dbDmsSchedulerTaskFileRecordService;

    @Override
    public void exec(Map<String, Object> params, String taskId) {
        FtpPublishParams ftpPublishParams = JSON.parseObject(JSON.toJSONString(params), FtpPublishParams.class);
        boolean automatic = ftpPublishParams.getAutomatic();
        HtScheduleJobDTO taskDTO = htScheduleJobService.findById(taskId);
        HtPathConfigurationDTO pathDTO = htPathConfigurationService.findById(taskDTO.getPathConfigId());
        if (automatic) {
            automaticPublish(taskDTO, ftpPublishParams, pathDTO);
        } else {
            manualPublish(ftpPublishParams,pathDTO);
        }
    }

    /**
     * 手动分发某个目录下的所有文件
     * @param params 参数信息
     * @param pathDTO 路径信息
     */
    private void manualPublish(FtpPublishParams params, HtPathConfigurationDTO pathDTO) {
        FTPUtil ftpUtil = new FTPUtil();
        String scanningPath = pathDTO.getScanningPath();
        logger.info("[手动分发任务]开始");
        recursionFile(params,scanningPath,ftpUtil,pathDTO);
        logger.info("[手动分发任务]结束");
    }

    private void recursionFile(FtpPublishParams params, String srcPath, FTPUtil ftpUtil,HtPathConfigurationDTO pathDTO) {
        File file = new File(srcPath);
        if (file.exists()) {
            logger.info("[手动分发任务-当前文件]{}",file.getAbsolutePath());
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                if (files != null) {
                    for (File f : files) {
                        recursionFile(params,f.getAbsolutePath(),ftpUtil,pathDTO);
                    }
                }
            } else {
                String host = params.getHost();
                int port = params.getPort();
                String password = params.getPassword();
                String username = params.getUsername();
                String targetPath = params.getTargetPath();
                FTPClient ftpClient = null;
                try {
                    ftpClient = ftpUtil.getFTPClient(host,port,username,password);
                    String srcFilePath = file.getAbsolutePath();
                    String destDirPath = targetPath + (file.getParent().substring(pathDTO.getScanningPath().length()));
                    boolean b = ftpUtil.uploadFile(ftpClient, srcFilePath, destDirPath);
                    if (b) {
                        logger.info("[手动分发任务-成功]文件路径：{}",srcFilePath);
                    } else {
                        logger.info("[手动分发任务-失败]文件路径：{}",srcFilePath);
                    }
                } finally {
                    if (ftpClient != null) {
                        ftpUtil.closeFTP(ftpClient);
                    }
                }
            }
        }
    }

    /**
     * 自动分发L2级数据
     * @param taskDTO 任务信息对象
     * @param params 参数信息
     * @param pathDTO 路径信息
     */
    private void automaticPublish(HtScheduleJobDTO taskDTO,FtpPublishParams params, HtPathConfigurationDTO pathDTO) {
        String companyName = params.getCompanyName();
        String fileType = params.getFileType();
        String host = params.getHost();
        String password = params.getPassword();
        Integer port = params.getPort();
        String resolution = params.getResolution();
        String satellite = params.getSatellite();
        String senor = params.getSenor();
        String targetPath = params.getTargetPath();
        String username = params.getUsername();
        String nearDate = params.getDay();
        String ipAddress = IpUtil.getLinuxLocalIp();
        List<DbDmsAlgorithmResultStoreDTO> list = dbDmsAlgorithmResultStoreService.specificationList(satellite, senor, resolution, fileType, nearDate);
        if(!list.isEmpty()){
            FTPUtil ftpUtil = new FTPUtil();
            List<String> allFileNameList = list.stream().map(DbDmsAlgorithmResultStoreDTO::getFilename).collect(Collectors.toList());
            if (!allFileNameList.isEmpty()) {
                List<DbDmsSchedulerTaskFileRecordDTO> alreadyUpload = dbDmsSchedulerTaskFileRecordService
                        .findAllByTaskIdAndFileNameIn(taskDTO.getId(), allFileNameList);
                Map<String, DbDmsSchedulerTaskFileRecordDTO> alreadyUploadMap = alreadyUpload.stream()
                        .collect(Collectors.toMap(DbDmsSchedulerTaskFileRecordDTO::getFileName, dto -> dto, (k1, k2) -> k2));
                list = list.stream().filter(dto -> !alreadyUploadMap.containsKey(dto.getFilename())).collect(Collectors.toList());
            }
            //生成记录表
            List<String> fileNameList = list.stream().map(DbDmsAlgorithmResultStoreDTO::getFilename).collect(Collectors.toList());
            dbDmsSchedulerTaskFileRecordService.prepareDataByFileNameList(taskDTO.getId(),fileNameList);
            ExecutorService threadPool = Executors.newFixedThreadPool(3);
            for (DbDmsAlgorithmResultStoreDTO dbDmsAlgorithmResultStoreDTO : list) {
                //记录运行数据
                threadPool.execute(() -> {
                    FTPClient ftpClient = null;
                    try {
                        dbDmsSchedulerTaskFileRecordService.dataExecution(taskDTO.getId(), dbDmsAlgorithmResultStoreDTO.getFilename());
                        String resultDataPath = dbDmsAlgorithmResultStoreDTO.getFilepath().replaceAll("/+","/");
                        String srcPath = pathDTO.getScanningPath() + File.separator + resultDataPath;
                        String ftpPath = targetPath + resultDataPath.substring(0,resultDataPath.lastIndexOf("/"));
                        ftpClient = ftpUtil.getFTPClient(host,port,username,password);
                        boolean b = ftpUtil.uploadFile(ftpClient, srcPath, ftpPath);
                        //记录结果
                        dbDmsSchedulerTaskFileRecordService.dataResults(taskDTO.getId(), dbDmsAlgorithmResultStoreDTO.getFilename(), b);
                        if (b) {
                            DbDmsProductDistributeRecodeDTO recodeDTO = new DbDmsProductDistributeRecodeDTO();
                            recodeDTO.setConpanyName(companyName);
                            recodeDTO.setDataLevel(dbDmsAlgorithmResultStoreDTO.getDataLevel());
                            recodeDTO.setDistriIp(ipAddress);
                            recodeDTO.setDistriTargetIp(host);
                            recodeDTO.setFileName(dbDmsAlgorithmResultStoreDTO.getFilename());
                            recodeDTO.setFileSize(dbDmsAlgorithmResultStoreDTO.getFilesize());
                            recodeDTO.setResolution(StringUtils.isNotBlank(dbDmsAlgorithmResultStoreDTO.getResolution()) ? Integer.valueOf(dbDmsAlgorithmResultStoreDTO.getResolution()) : null);
                            recodeDTO.setSensor(dbDmsAlgorithmResultStoreDTO.getSensor());
                            recodeDTO.setSatellite(dbDmsAlgorithmResultStoreDTO.getSatellite());
                            recodeDTO.setDistritime(new Date());
                            recodeDTO.setDistriType(PRODUCT_DISTRIBUTE_TYPE);
                            recodeDTO.setProductIdentify(dbDmsAlgorithmResultStoreDTO.getProductIdentify());
                            //设置分发成功
                            recodeDTO.setDistriState(1);
                            //设置为自动分发类型
                            recodeDTO.setDistriAuto(1);
                            dbDmsProductDistributeRecodeService.addEntity(recodeDTO);
                        }
                    }finally {
                        if (ftpClient != null) {
                            ftpUtil.closeFTP(ftpClient);
                        }
                    }
                });
            }
            threadPool.shutdown();
        }else{
            logger.info("没有符合条件的文件要推送-----------");
        }
    }
}
